package com.cll.learn.monitor.thread;

import com.alibaba.fastjson.JSONObject;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 描述信息:
 *
 * @author CLL
 * @version 1.0
 * @date 2020/9/29 10:26
 */
public class CustomThreadPoolExecutor extends ThreadPoolExecutor {

    private static final Logger logger = LoggerFactory.getLogger(ThreadPoolExecutor.class);

    /**
     * 线程池数量
     */
    public static final AtomicInteger POOL_NUMBER = new AtomicInteger(0);

    /**
     * 线程池名称
     */
    @Getter
    private String name;



    public CustomThreadPoolExecutor(int corePoolSize,
                             int maximumPoolSize,
                             long keepAliveTime,
                             TimeUnit unit,
                             BlockingQueue<Runnable> workQueue,
                             ThreadFactory threadFactory,
                             RejectedExecutionHandler handler,
                             String name) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
        this.name = (name + "-" + POOL_NUMBER.incrementAndGet());
        if (logger.isDebugEnabled()) {
            logger.debug(">>>>>> create thread pool. pool name = {}, pool index = {}", this.name, POOL_NUMBER.get());
        }

        CheckPoolTask.addThreadPool(this);
    }

    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        if (logger.isDebugEnabled()) {
            logger.debug(">>>>>> before execute task。t = {}, r = {}", JSONObject.toJSONString(t), JSONObject.toJSONString(r));
        }
        super.beforeExecute(t, r);
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        if (logger.isDebugEnabled()) {
            logger.debug(">>>>>> after execute task。r = {}, t = {}", JSONObject.toJSONString(r), JSONObject.toJSONString(t));
        }
        super.afterExecute(r, t);
    }

    @Override
    protected void terminated() {
        logger.info("===>>> thread pool closed = {}.", JSONObject.toJSONString(this));
        super.terminated();
    }

    @Override
    public void execute(Runnable command) {
        if (logger.isDebugEnabled()) {
            logger.debug(">>>>>> execute task。r = {}", JSONObject.toJSONString(command));
        }
        super.execute(wrapTask(command, threadPoolStackTrace()));
    }

    @Override
    public Future<?> submit(Runnable task) {
        if (logger.isDebugEnabled()) {
            logger.debug("===>>> 执行submit方法。task = {}", JSONObject.toJSONString(task));
        }
        return super.submit(wrapTask(task, threadPoolStackTrace()));
    }

    /**
     * 自定义线程池抛出异常
     * @return  异常提示细腻些
     */
    private Exception threadPoolStackTrace(){
        return new ThreadPoolException("custom thread pool throw exception. stack trace is flow.");
    }

    private Runnable wrapTask(final Runnable task, final Exception stackTrace){
        return () -> {
            try {
                task.run();
            } catch (Exception e) {
                logger.error("****** exception message info : " + stackTrace.getMessage(), stackTrace);
                throw e;
            }
        };
    }
}
